﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Symbol.RFID3;
using System.Threading;
using System.Media;
using System.IO;
using System.Reflection;
using Db4objects.Db4o;
using BE;

namespace DHLAppMovil
{
    public partial class FrmApp : Form
    {
        internal RFIDReader m_ReaderAPI;
        internal ReaderManagement m_ReaderMgmt;
        private TimeSpan m_StartTime;
        internal AccessOperationResult m_AccessOpResult;
        private UpdateStatus m_UpdateStatusHandler = null;
        private delegate void UpdateRead(Events.ReadEventData eventData);
        private UpdateRead m_UpdateReadHandler = null;
        private delegate void UpdateStatus(Events.StatusEventData eventData);
        internal bool m_IsConnected;
        internal uint m_DurationTriggerTime;
        private Symbol.RFID3.TriggerInfo m_TriggerInfo = null;
        private Boolean m_isReading = false;
        internal List<int> arregloEnteros;
        private FrmPersona frmPersona=null;
        private FrmAuto frmAuto=null;
        public static Persona persona;
        public static string nameDB = "bd.db4o";

        internal class AccessOperationResult
        {
            public string m_Result;
            

            public ACCESS_OPERATION_CODE m_OpCode;
            public AutoResetEvent m_AccessCompleteEvent;
            public AccessOperationResult()
            {
                m_Result = "";
                m_OpCode = ACCESS_OPERATION_CODE.ACCESS_OPERATION_READ;
                m_AccessCompleteEvent = new AutoResetEvent(false);
            }
            
        }

        public FrmApp()
        {
            InitializeComponent();
            m_UpdateStatusHandler = new UpdateStatus(myUpdateStatus);
            m_UpdateReadHandler = new UpdateRead(myUpdateRead);
            m_ReaderMgmt = new ReaderManagement();
            m_AccessOpResult = new AccessOperationResult();
            arregloEnteros = new List<int>();
        }

       

        private void Form1_Load(object sender, EventArgs e)
        {
            //Vamos a usar RFID y encender el trigger
            this.Connect("Connect");

            persona = null;

            //Configuracion de las antenas

            ushort[] antID = m_ReaderAPI.Config.Antennas.AvailableAntennas;
            if (antID.Length > 0)
            {
                for (int i = 0; i < m_ReaderAPI.Config.Antennas.Length; i++)
                {
                    Antennas.Config antConfig =
                    m_ReaderAPI.Config.Antennas[antID[i]].GetConfig();
                    antConfig.TransmitPowerIndex = ushort.Parse(MobileConfiguration.Settings["PotenciaAntenas"]);
                    m_ReaderAPI.Config.Antennas[antID[i]].SetConfig(antConfig);
                }
            }

            frmPersona = new FrmPersona();
        }

        private void myUpdateStatus(Events.StatusEventData eventData)
        {
            //string caso = "caso";
            switch (eventData.StatusEventType)
            {
                case Symbol.RFID3.Events.STATUS_EVENT_TYPE.INVENTORY_START_EVENT:
                    //readButton.Text = "Stop Reading";
                    arregloEnteros = new List<int>();
                    m_isReading = true;
                    break;
                case Symbol.RFID3.Events.STATUS_EVENT_TYPE.INVENTORY_STOP_EVENT:
                    //readButton.Text = "Start Reading";
                    m_isReading = false;

                    if (this.m_DurationTriggerTime > 0)
                    {
                        TimeSpan triggerDuration = TimeSpan.FromMilliseconds(m_DurationTriggerTime);
                        readTimeValueLabel.Text = triggerDuration.Seconds + "." + triggerDuration.Milliseconds / 100 + " Sec";
                    }
                    break;
                case Symbol.RFID3.Events.STATUS_EVENT_TYPE.ACCESS_START_EVENT:
                    //readButton.Text = "Stop Reading";
                    m_isReading = true;
                    break;
                case Symbol.RFID3.Events.STATUS_EVENT_TYPE.ACCESS_STOP_EVENT:
                    //readButton.Text = "Start Reading";
                    m_isReading = false;
                    m_AccessOpResult.m_AccessCompleteEvent.Set();
                    break;
                case Symbol.RFID3.Events.STATUS_EVENT_TYPE.HANDHELD_TRIGGER_EVENT:
                    TriggerInfo triggerInfo = getTriggerInfo();
                    if (eventData.HandheldTriggerEventData.HandheldTriggerEvent == HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED &&
                        triggerInfo.StartTrigger.Type == START_TRIGGER_TYPE.START_TRIGGER_TYPE_IMMEDIATE)
                    {
                        // Lets start the inventory upon GPI event even if the StartTrigger is configured as immediate
                        processUIOrGPIEvent(eventData.HandheldTriggerEventData.HandheldTriggerEvent == HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED);
                    }
                    if (eventData.HandheldTriggerEventData.HandheldTriggerEvent == HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_RELEASED &&
                        triggerInfo.StopTrigger.Type == STOP_TRIGGER_TYPE.STOP_TRIGGER_TYPE_IMMEDIATE)
                    {
                        processUIOrGPIEvent(eventData.HandheldTriggerEventData.HandheldTriggerEvent == HANDHELD_TRIGGER_EVENT_TYPE.HANDHELD_TRIGGER_PRESSED);
                    }
                    break;
                default:
                    break;
            }
             
        }

        public void Events_StatusNotify(object sender, Events.StatusEventArgs args)
        {
            this.Invoke(m_UpdateStatusHandler, new object[] { args.StatusEventData });
        }

        private void Events_ReadNotify(object sender, Events.ReadEventArgs args)
        {
            this.Invoke(m_UpdateReadHandler, new object[] { args.ReadEventData.TagData.TagID });
        }

        internal void notifyUser(string notificationMessage, string notificationSource)
        {
            MessageBox.Show(notificationMessage, notificationSource);
        }

        private void StopReading()
        {
            /*
             *  Update Read Time and Tags Read Count 
             */
            if (this.m_DurationTriggerTime == 0)
            {
                TimeSpan duration = TimeSpan.FromMilliseconds(Environment.TickCount).Subtract(m_StartTime).Duration();
                readTimeValueLabel.Text = duration.Hours + ":" + duration.Minutes + ":" + duration.Seconds + "." + duration.Milliseconds / 100 + " Sec";
            }

            try
            {
                if (m_ReaderAPI.Actions.TagAccess.OperationSequence.Length > 0)
                {
                    m_ReaderAPI.Actions.TagAccess.OperationSequence.StopSequence();
                }
                else
                {
                    m_ReaderAPI.Actions.Inventory.Stop();
                    m_isReading = false;
                }
            }
            catch (InvalidOperationException ioe)
            {
                notifyUser("InvalidOperationException" + ioe.Message, "Stop Operation");
            }
            catch (OperationFailureException ofe)
            {
                notifyUser("OperationFailureException:" + ofe.StatusDescription, "Stop Read");
            }
            catch (InvalidUsageException iue)
            {
                notifyUser("InvalidUsageException:" + iue.Info, "Stop Read");
            }
            catch (Exception ex)
            {
                notifyUser("Exception:" + ex.Message, "Stop Read");
            }
        }

        private void CloseForm()
        {
            try
            {
                if (m_IsConnected)
                {
                    m_ReaderAPI.Events.ReadNotify -= Events_ReadNotify;
                    m_ReaderAPI.Events.StatusNotify -= Events_StatusNotify;
                    StopReading();
                    m_ReaderAPI.Disconnect();
                }
                m_ReaderMgmt.Dispose();
                this.Dispose();
            }
            catch (Exception ex)
            {
                notifyUser(ex.Message, "Close");
            }
        }

        private void processUIOrGPIEvent(bool startRead)
        {
            try
            {
                if (m_IsConnected)
                {
                    if (startRead)
                    {
                        StartReading();
                    }
                    else
                    {
                        StopReading();
                    }
                }
                else
                {
                    notifyUser("Please connect to a reader", "Read Operation");
                }
            }
            catch (OperationFailureException ex)
            {
                notifyUser(ex.VendorMessage, "Read Operation");
            }
        }

        public Symbol.RFID3.TriggerInfo getTriggerInfo()
        {
            if (null == m_TriggerInfo)
            {
                m_TriggerInfo = new TriggerInfo();
            }
            //m_TriggerInfo.EnableTagEventReport = m_AppForm.autonomousMode_CB.Checked;
            m_TriggerInfo.EnableTagEventReport = false;
            return m_TriggerInfo;
        }

        private void StartReading()
        {
            if (!m_isReading)
            {
                try
                {
                    //if (m_ReaderAPI.Actions.TagAccess.OperationSequence.Length > 0)
                    //{
                    //    m_ReaderAPI.Actions.TagAccess.OperationSequence.PerformSequence(m_AccessFilterForm.getFilter(),
                    //            getTriggerInfo(), m_AntennaInfoForm.getInfo());
                    //}
                    //else
                    //{
                    
                        //this.inventoryList.Items.Clear();
                        //this.m_TagTable.Clear();
                        //this.m_TagTotalCount = 0;

                        //if (getTriggerInfo().StartTrigger.Type == START_TRIGGER_TYPE.START_TRIGGER_TYPE_PERIODIC)
                            //readButton.Text = "Stop Reading";
                    //}
                    m_ReaderAPI.Actions.Inventory.Perform();
                        
                }
                catch (InvalidOperationException ioe)
                {
                    notifyUser("InvalidOperationException" + ioe.Message, "Read Operation");
                }
                catch (OperationFailureException ofe)
                {
                    notifyUser("OperationFailureException:" + ofe.StatusDescription, "Read Operation");
                }
                catch (InvalidUsageException iue)
                {
                    notifyUser("InvalidUsageException:" + iue.Info, "Read Operation");
                }
                catch (Exception ex)
                {
                    notifyUser("Exception:" + ex.Message, "Read Operation");
                }
                m_StartTime = TimeSpan.FromMilliseconds(Environment.TickCount);
            }
        }

        private void myUpdateRead(Events.ReadEventData eventData)
        {
            Symbol.RFID3.TagData[] tagData = m_ReaderAPI.Actions.GetReadTags(1000);
            if (tagData != null)
            {
                int intEPC = 0;
                bool esInt = false;
                for (int nIndex = 0; nIndex < tagData.Length; nIndex++)
                {
                    //Tiene que ser numero
                    bool flagSonido = false;        
                    try 
                    {
                        int intEPCString = int.Parse(tagData[nIndex].TagID);
                        esInt = true;
                        intEPC = intEPCString;
                    }
                    catch (Exception exc) 
                    {
                        esInt = false;
                        intEPC = 0;
                    }

                    if (esInt) 
                    {
                        
                        if (!arregloEnteros.Contains(intEPC)) 
                        {
                            string cad = "";

                            Stream audioStream= new MemoryStream(Properties.Resources.sonido);
                            Stream audioStreamAlarma = new MemoryStream(Properties.Resources.alarma);

                            if (tagData[nIndex].TagID.EndsWith("1"))
                            {
                                
                                var result = DatabaseContext.Current.Client.QueryByExample(new Persona(intEPC / 10));
                                List<Persona> listaPersonas = new List<Persona>();
                                if (result.Count == 0) 
                                {
                                    flagSonido = false;
                                    if (frmAuto != null)
                                    {
                                        frmAuto.Close();
                                    }

                                    if (frmPersona != null)
                                    {
                                        frmPersona.Close();
                                    }
                                    frmPersona = new FrmPersona();
                                    frmPersona.lblCargo.Text = "ERROR";
                                    frmPersona.lblNombre.Text = "ERROR NO EXISTE";
                                    frmPersona.lblCodigo.Text = "ERROR";
                                    frmPersona.lblActivo.Text = "ERROR";
                                    frmPersona.Show();
                                }
                                foreach (Persona c in result)
                                {
                                    flagSonido = true;
                                    if (frmPersona != null) 
                                    {
                                        frmPersona.Close();
                                    }
                                    if (frmAuto != null) 
                                    {
                                        frmAuto.Close();
                                    }
                                    frmPersona = new FrmPersona();
                                    if(c.Imagen!=null)
                                    {
                                        byte[] bytes = new byte[2048];
                                    System.IO.MemoryStream ms = new System.IO.MemoryStream(c.Imagen);
                                    Image im = new Bitmap(ms);
                                    frmPersona.pictureBox1.Image = im;
                                    }
                                    
                                    frmPersona.lblCargo.Text = c.Cargo + " / "+c.Unidad;
                                    frmPersona.lblNombre.Text = c.Nombre;
                                    frmPersona.lblCodigo.Text = c.Codigo;
                                    if (c.Condicion == 1)
                                    {
                                        frmPersona.lblActivo.Text = "ACTIVO";
                                    }
                                    else
                                    {
                                        frmPersona.lblActivo.Text = "CESADO";
                                        flagSonido = false;
                                    }
                                    frmPersona.Show();

                                    FrmApp.persona = c;
                                }


                            }
                            else 
                            {
                                if (tagData[nIndex].TagID.EndsWith("2"))
                                {
                                    //Es un movil
                                    var result = DatabaseContext.Current.Client.QueryByExample(new Vehiculo(intEPC / 10));
                                    List<Vehiculo> listaVehiculos = new List<Vehiculo>();
                                    if (result.Count == 0) 
                                    {
                                        flagSonido = false;
                                        if (frmAuto != null)
                                        {
                                            frmAuto.Close();
                                        }

                                        if (frmPersona != null)
                                        {
                                            frmPersona.Close();
                                        }
                                        frmAuto = new FrmAuto();
                                        frmAuto.lblPlaca.Text = "ERROR NO EXISTE";
                                        frmAuto.lblMarca.Text = "ERROR NO EXISTE";
                                        frmAuto.lblModelo.Text = "ERROR NO EXISTE";
                                        frmAuto.lblPropietario.Text = "ERROR NO EXISTE";
                                        frmAuto.lblColor.Text = "ERROR NO EXISTE";
                                        frmAuto.Show();
                                    }
                                    foreach (Vehiculo v in result)
                                    {
                                        flagSonido = true;
                                        if (frmAuto != null)
                                        {
                                            frmAuto.Close();
                                        }

                                        if (frmPersona != null)
                                        {
                                            frmPersona.Close();
                                        }
                                        frmAuto = new FrmAuto();
                                        frmAuto.lblPlaca.Text = v.Placa;
                                        frmAuto.lblMarca.Text = v.Marca;
                                        frmAuto.lblModelo.Text = v.Modelo;
                                        frmAuto.lblPropietario.Text = v.Propietario;
                                        frmAuto.lblColor.Text = v.Color;
                                        if (v.Imagen != null)
                                        {
                                            byte[] bytes = new byte[2048];
                                            System.IO.MemoryStream ms = new System.IO.MemoryStream(v.Imagen);
                                            Image im = new Bitmap(ms);
                                            frmAuto.pictureBox1.Image = im;
                                        }
                                        FrmAuto.vehiculo = v;
                                        frmAuto.Show();
                                    }
                                }
                                else 
                                {
                                    flagSonido = false;
                                    
                                }
                            }

                            SoundPlayer player;

                            if (flagSonido)
                            {
                                player = new SoundPlayer(audioStream);
                                player.Play();
                                arregloEnteros.Add(intEPC);
                            }
                            else 
                            {
                                player = new SoundPlayer(audioStreamAlarma);
                                player.Play();
                                arregloEnteros.Add(intEPC);
                            }
                            
                        }
                    }
                   
                }
                    
                
                /*
                 *  Update front panel Tag Count while changing inventory list
                 */
                //this.totalTagValueLabel.Text = m_TagTable.Count + "(" + m_TagTotalCount + ")";
            }
        }

        internal void Connect(string status)
        {
            string ipAddress = "127.0.0.1";
            string puerto = "5084";
            if (status == "Connect")
            {
                uint port = uint.Parse(puerto);
                m_ReaderAPI = new RFIDReader(ipAddress, port, 0);

                try
                {
                    m_ReaderAPI.Connect();

                    /*
                     *  Events Registration
                     */
                    m_ReaderAPI.Events.AttachTagDataWithReadEvent = false;
                    m_ReaderAPI.Events.ReadNotify += new Events.ReadNotifyHandler(Events_ReadNotify);
                    m_ReaderAPI.Events.StatusNotify += new Events.StatusNotifyHandler(Events_StatusNotify);
                    m_ReaderAPI.Events.NotifyBufferFullWarningEvent = true;
                    m_ReaderAPI.Events.NotifyBufferFullEvent = true;
                    m_ReaderAPI.Events.NotifyReaderDisconnectEvent = true;
                    m_ReaderAPI.Events.NotifyAccessStartEvent = true;
                    m_ReaderAPI.Events.NotifyAccessStopEvent = true;
                    m_ReaderAPI.Events.NotifyInventoryStartEvent = true;
                    m_ReaderAPI.Events.NotifyInventoryStopEvent = true;
                    m_ReaderAPI.Events.NotifyReaderExceptionEvent = true;
                    m_ReaderAPI.Events.NotifyHandheldTriggerEvent = true;

                    /*
                     * Label setup
                     */
                    this.Text = ipAddress;
                    
                    //this.m_ConnectionForm.connectionButton.Text = "Disconnect";
                    //if (m_ConnectionForm.Visible)
                    //{
                    //    this.m_ConnectionForm.Close();
                    //}
                }
                catch (OperationFailureException ofe)
                {
                    notifyUser(ofe.StatusDescription, "Connect");
                }
            }
            else if (status == "Disconnect")
            {
                //if (!m_ReaderInitiatedDisconnectionReceived)
                //{
                //    try
                //    {
                //        m_ReaderAPI.Disconnect();
                //    }
                //    catch (OperationFailureException ofe)
                //    {
                //        notifyUser(ofe.VendorMessage, "Connect");
                //    }
                //}


            }
            m_IsConnected = m_ReaderAPI.IsConnected;

        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void label1_ParentChanged(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            CloseForm();
            Application.Exit();
            
        }
    }
}